added samples
[windows-sources.git] / sdk / samples / all in on code / Visual Studio 2008 / CSNamedPipeClient / ReadMe.txt
blob9d40690958271a7e8b4f66d9a906dbb21ef97693
1 ========================================================================
2     CONSOLE APPLICATION : CSNamedPipeClient Project Overview
3 ========================================================================
5 /////////////////////////////////////////////////////////////////////////////
6 Summary:
8 Named pipe is a mechanism for one-way or duplex inter-process communication 
9 between the pipe server and one or more pipe clients in the local machine or 
10 across the computers in the intranet:
12 PIPE_ACCESS_INBOUND:
13 Client (GENERIC_WRITE) ---> Server (GENERIC_READ)
15 PIPE_ACCESS_OUTBOUND:
16 Client (GENERIC_READ) <--- Server (GENERIC_WRITE)
18 PIPE_ACCESS_DUPLEX:
19 Client (GENERIC_READ or GENERIC_WRITE, or both) <--> 
20 Server (GENERIC_READ and GENERIC_WRITE)
22 This code sample demonstrate two methods to use named pipe in Visual C#.
24 1. Use the System.IO.Pipes namespace
26 The System.IO.Pipes namespace contains types that provide a means for 
27 interprocess communication through anonymous and/or named pipes. 
28 http://msdn.microsoft.com/en-us/library/system.io.pipes.aspx
29 These classes make the programming of named pipe in .NET much easier and 
30 safer than P/Invoking native APIs directly. However, the System.IO.Pipes 
31 namespace is not available before .NET Framework 3.5. So, if you are 
32 programming against .NET Framework 2.0, you have to P/Invoke native APIs 
33 to use named pipe.
35 The sample code in SystemIONamedPipeClient.Run() uses the 
36 Systen.IO.Pipes.NamedPipeClientStream class to connect to the named pipe 
37 "\\.\pipe\SamplePipe" to perform message-based duplex communication. The 
38 client then writes a message to the pipe and receives the response from the 
39 pipe server.
41 2. P/Invoke the native APIs related to named pipe operations.
43 The .NET interop services make it possible to call native APIs related to 
44 named pipe operations from .NET. The sample code in 
45 NativeNamedPipeClient.Run() demonstrates calling CreateFile to connect to 
46 the named pipe "\\.\pipe\SamplePipe" with the GENERIC_READ and 
47 GENERIC_WRITE accesses, and calling WriteFile and ReadFile to write a 
48 message to the pipe and receive the response from the pipe server. Please 
49 note that if you are programming against .NET Framework 3.5 or any newer 
50 releases of .NET Framework, it is safer and easier to use the types in the 
51 System.IO.Pipes namespace to operate named pipes.
54 /////////////////////////////////////////////////////////////////////////////
55 Demo:
57 The following steps walk through a demonstration of the named pipe sample.
59 Step1. After you successfully build the CSNamedPipeClient and 
60 CSNamedPipeServer sample projects in Visual Studio 2008, you will get the 
61 applications: CSNamedPipeClient.exe and CSNamedPipeServer.exe. 
63 Step2. Run CSNamedPipeServer.exe in a command prompt to start up the server 
64 end of the named pipe. If the command is "CSNamedPipeServer.exe", the pipe 
65 server is created by the types in the System.IO.Pipes namespace. If the 
66 command is "CSNamedPipeServer.exe -native", the pipe server is created by 
67 P/Invoking the native APIs related to named pipe operations. In both cases, 
68 the application outputs the following information in the command prompt if 
69 the pipe is created successfully.
71  Server:
72   The named pipe (\\.\pipe\SamplePipe) is created.
73   Waiting for the client's connection...
75 Step3. Run CSNamedPipeClient.exe in another command prompt to start up the 
76 client end of the named pipe. If the command is "CSNamedPipeClient.exe", the 
77 client connects to the pipe by using the types in the System.IO.Pipes 
78 namespace. If the command is "CSNamedPipeClient.exe -native", the client 
79 connects to the pipe by P/Invoking the native APIs related to named pipe 
80 operations. In both cases, the application should output the message below 
81 in the command prompt when the client successfully connects to the named pipe.
83  Client:
84   The named pipe (\\.\pipe\SamplePipe) is connected.
86 In the meantime, the server application outputs this message to indicate that 
87 the pipe is connected by a client.
89  Server:
90   Client is connected.
92 Step4. The client attempts to write a message to the named pipe. You will see 
93 the message below in the commond prompt running the client application.
95  Client:
96   Send 56 bytes to server: "Default request from client"
98 When the server application reads the message from the client, it prints:
100  Server:
101   Receive 56 bytes from client: "Default request from client"
103 Next, the server writes a response to the pipe.
105  Server:
106   Send 58 bytes to client: "Default response from server"
108 And the client receives the response:
110  Client:
111   Receive 58 bytes from server: "Default response from server"
113 The connection is disconnected and the pipe is closed after that.
116 /////////////////////////////////////////////////////////////////////////////
117 Sample Relation:
118 (The relationship between the current sample and the rest samples in 
119 Microsoft All-In-One Code Framework http://1code.codeplex.com)
121 CSNamedPipeClient -> CSNamedPipeServer/VBNamedPipeServer/CppNamedPipeServer
122 CSNamedPipeClient is the client end of the named pipe. CSNamedPipeServer, 
123 VBNamedPipeServer and CppNamedPipeServer can be the server ends that create 
124 the named pipe.
126 CSNamedPipeClient - VBNamedPipeClient - CppNamedPipeClient
127 CSNamedPipeClient, VBNamedPipeClient and CppNamedPipeServer are the same 
128 named pipe client ends written in three different programming languages.
131 /////////////////////////////////////////////////////////////////////////////
132 Code Logic:
134 A. Named pipe client by using the System.IO.Pipes namespace. 
135 (SystemIONamedPipeClient.Run())
137 1. Create a NamedPipeClientStream object and specify the pipe server, name, 
138 pipe direction, options, etc. 
140     pipeClient = new NamedPipeClientStream(
141         Program.SERVER_NAME,        // The server name
142         Program.PIPE_NAME,          // The unique pipe name
143         PipeDirection.InOut,        // The pipe is duplex
144         PipeOptions.None            // No additional parameters
145         );
147 2. Connect to the named pipe by calling NamedPipeClientStream.Connect().
149     pipeClient.Connect(5000);
151 3. Set the read mode and the blocking mode of the named pipe. In this sample, 
152 we set data to be read from the pipe as a stream of messages. This allows a 
153 reading process to read varying-length messages precisely as sent by the 
154 writing process. In this mode, you should not use StreamWriter to write the 
155 pipe, or use StreamReader to read the pipe. You can read more about the 
156 difference from http://go.microsoft.com/?linkid=9721786.
158     pipeClient.ReadMode = PipeTransmissionMode.Message;
160 4. Send a message to the pipe server and receive its response through 
161 NamedPipeClientStream.Read and NamedPipeClientStream.Write. Because 
162 pipeClient.ReadMode = PipeTransmissionMode.Message, you should not use 
163 StreamWriter to write the pipe, or use StreamReader to read the pipe.
165     // 
166     // Send a request from client to server
167     // 
169     string message = Program.REQUEST_MESSAGE;
170     byte[] bRequest = Encoding.Unicode.GetBytes(message);
171     int cbRequest = bRequest.Length;
173     pipeClient.Write(bRequest, 0, cbRequest);
175     Console.WriteLine("Send {0} bytes to server: \"{1}\"",
176         cbRequest, message.TrimEnd('\0'));
178     //
179     // Receive a response from server.
180     // 
182     do
183     {
184         byte[] bResponse = new byte[Program.BUFFER_SIZE];
185         int cbResponse = bResponse.Length, cbRead;
187         cbRead = pipeClient.Read(bResponse, 0, cbResponse);
189         // Unicode-encode the received byte array and trim all the 
190         // '\0' characters at the end.
191         message = Encoding.Unicode.GetString(bResponse).TrimEnd('\0');
192         Console.WriteLine("Receive {0} bytes from server: \"{1}\"",
193             cbRead, message);
194     }
195     while (!pipeClient.IsMessageComplete);
197 5. Close the client end of the pipe by calling NamedPipeClientStream.Close().
199     pipeClient.Close();
201 -------------------------
203 B. Named pipe client by P/Invoke the native APIs related to named pipe 
204 operations. (NativeNamedPipeClient.Run())
206 1. Try to connect to a named pipe by P/Invoking CreateFile and specifying the 
207 target pipe server, name, desired access, etc. 
209     hNamedPipe = NativeMethod.CreateFile(
210         Program.FULL_PIPE_NAME,                 // Pipe name
211         FileDesiredAccess.GENERIC_READ |        // Read access
212         FileDesiredAccess.GENERIC_WRITE,        // Write access
213         FileShareMode.Zero,                     // No sharing 
214         null,                                   // Default security attributes
215         FileCreationDisposition.OPEN_EXISTING,  // Opens existing pipe
216         0,                                      // Default attributes
217         IntPtr.Zero                             // No template file
218         );
220 If all pipe instances are busy, wait for 5 seconds and connect again.
222     if (!NativeMethod.WaitNamedPipe(Program.FULL_PIPE_NAME, 5000))
223     {
224         throw new Win32Exception();
225     }
227 2. Set the read mode and the blocking mode of the named pipe. In this sample, 
228 we set data to be read from the pipe as a stream of messages.
230     PipeMode mode = PipeMode.PIPE_READMODE_MESSAGE;
231     if (!NativeMethod.SetNamedPipeHandleState(hNamedPipe, ref mode,
232         IntPtr.Zero, IntPtr.Zero))
233     {
234         throw new Win32Exception();
235     }
237 3. Send a message to the pipe server and receive its response by calling 
238 the WriteFile and ReadFile functions.
240     // 
241     // Send a request from client to server
242     // 
244     string message = Program.REQUEST_MESSAGE;
245     byte[] bRequest = Encoding.Unicode.GetBytes(message);
246     int cbRequest = bRequest.Length, cbWritten;
248     if (!NativeMethod.WriteFile(
249         hNamedPipe,     // Handle of the pipe
250         bRequest,       // Message to be written
251         cbRequest,      // Number of bytes to write
252         out cbWritten,  // Number of bytes written
253         IntPtr.Zero     // Not overlapped
254         ))
255     {
256         throw new Win32Exception();
257     }
259     Console.WriteLine("Send {0} bytes to server: \"{1}\"", 
260         cbWritten, message.TrimEnd('\0'));
262     //
263     // Receive a response from server.
264     // 
266     bool finishRead = false;
267     do
268     {
269         byte[] bResponse = new byte[Program.BUFFER_SIZE];
270         int cbResponse = bResponse.Length, cbRead;
272         finishRead = NativeMethod.ReadFile(
273             hNamedPipe,             // Handle of the pipe
274             bResponse,              // Buffer to receive data
275             cbResponse,             // Size of buffer in bytes
276             out cbRead,             // Number of bytes read 
277             IntPtr.Zero             // Not overlapped 
278             );
280         if (!finishRead && 
281             Marshal.GetLastWin32Error() != ERROR_MORE_DATA)
282         {
283             throw new Win32Exception();
284         }
286         // Unicode-encode the received byte array and trim all the 
287         // '\0' characters at the end.
288         message = Encoding.Unicode.GetString(bResponse).TrimEnd('\0');
289         Console.WriteLine("Receive {0} bytes from server: \"{1}\"",
290             cbRead, message);
291     }
292     while (!finishRead);  // Repeat loop if ERROR_MORE_DATA
294 4. Close the pipe.
296     hNamedPipe.Close();
299 /////////////////////////////////////////////////////////////////////////////
300 References:
302 MSDN: System.IO.Pipes Namespace
303 http://msdn.microsoft.com/en-us/library/system.io.pipes.aspx
305 MSDN: NamedPipeClientStream
306 http://msdn.microsoft.com/en-us/library/system.io.pipes.namedpipeclientstream.aspx
308 How to: Use Named Pipes to Communicate Between Processes over a Network
309 http://msdn.microsoft.com/en-us/library/bb546085.aspx
311 Introducing Pipes [Justin Van Patten]
312 http://blogs.msdn.com/bclteam/archive/2006/12/07/introducing-pipes-justin-van-patten.aspx
315 /////////////////////////////////////////////////////////////////////////////